package com.shrcl.engineerprocess.domain.impl;

import com.google.common.base.Objects;
import com.shrcl.engineerprocess.domain.EngineerDAO;
import com.shrcl.engineerprocess.domain.EngineerLevel;
import com.shrcl.engineerprocess.domain.EngineerLevelSalary;
import com.shrcl.engineerprocess.domain.MonthlyLevelCost;
import com.shrcl.engineerprocess.domain.impl.EngineerLevelImpl;
import com.shrcl.engineerprocess.domain.impl.MonthlyLevelCostImpl;
import com.shrcl.engineerprocess.domain.proxy.EngineerLevelSalaryProxy;
import edu.fudan.mylang.pf.BaseModelObject;
import edu.fudan.mylang.pf.IObjectFactory;
import edu.fudan.mylang.utils.DateUtil;
import java.util.Collection;
import java.util.Date;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.DiscriminatorColumn;
import javax.persistence.DiscriminatorValue;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import org.eclipse.xtext.xbase.lib.Functions.Function1;
import org.eclipse.xtext.xbase.lib.IterableExtensions;
import org.eclipse.xtext.xbase.lib.ListExtensions;
import org.eclipse.xtext.xbase.lib.ObjectExtensions;
import org.eclipse.xtext.xbase.lib.Procedures.Procedure1;
import org.hibernate.annotations.DiscriminatorOptions;
import org.springframework.beans.factory.BeanFactory;

@Entity
@DiscriminatorValue("ENGINEERLEVELSALARY_TYPE")
@DiscriminatorOptions(force = true)
@DiscriminatorColumn(length = 64)
@Table(name = "engineerlevelsalary")
public class EngineerLevelSalaryImpl extends BaseModelObject implements EngineerLevelSalary {
  public EngineerLevelSalaryImpl() {
    super();
  }
  
  @JoinColumn(name = "level_id")
  @ManyToOne(targetEntity = EngineerLevelImpl.class, cascade = { CascadeType.MERGE, CascadeType.PERSIST })
  private EngineerLevel level;
  
  public EngineerLevel getLevel() {
    return this.level;
  }
  
  public EngineerLevelSalary setLevel(final EngineerLevel level) {
    this.level = level;
    return this;			
    
  }
  
  @ManyToMany(targetEntity = MonthlyLevelCostImpl.class)
  @JoinTable(name = "m2m_engineerlevelsalary_monthlylevelcost", joinColumns = @JoinColumn(name = "engineerlevelsalary_id") , inverseJoinColumns = @JoinColumn(name = "monthlyLevelCost_inv_id") )
  private Collection<MonthlyLevelCost> monthlyLevelCost = new java.util.ArrayList<com.shrcl.engineerprocess.domain.MonthlyLevelCost>();;
  
  public Collection<MonthlyLevelCost> getMonthlyLevelCost() {
    return this.monthlyLevelCost;
  }
  
  public EngineerLevelSalary setMonthlyLevelCost(final Iterable<MonthlyLevelCost> monthlyLevelCost) {
    removeAllMonthlyLevelCost();
    for(MonthlyLevelCost ca : monthlyLevelCost){
    	addtoMonthlyLevelCost(ca);
    }
    return this;		
    
  }
  
  public EngineerLevelSalary addtoMonthlyLevelCost(final MonthlyLevelCost monthlyLevelCost) {
    this.monthlyLevelCost.add(monthlyLevelCost);
    return this;
    
  }
  
  public EngineerLevelSalary removeAllMonthlyLevelCost() {
    this.monthlyLevelCost.clear();
    return this;	
    
  }
  
  public EngineerLevelSalary removeFromMonthlyLevelCost(final MonthlyLevelCost monthlyLevelCost) {
    this.monthlyLevelCost.remove(monthlyLevelCost);
    return this;
    
  }
  
  public void updateCost(final Date mon) {
    BeanFactory _beanFactory = this.getBeanFactory();
    final EngineerDAO engineerDAO = _beanFactory.<EngineerDAO>getBean(EngineerDAO.class);
    final Function1<MonthlyLevelCost,Boolean> _function = new Function1<MonthlyLevelCost,Boolean>() {
        public Boolean apply(final MonthlyLevelCost it) {
          Date _month = it.getMonth();
          Date _trim2Month = DateUtil.trim2Month(_month);
          Date _trim2Month_1 = DateUtil.trim2Month(mon);
          boolean _equals = Objects.equal(_trim2Month, _trim2Month_1);
          return Boolean.valueOf(_equals);
        }
      };
    MonthlyLevelCost levelCost = this.monthlyLevelCost==null?(MonthlyLevelCost)null:IterableExtensions.<MonthlyLevelCost>findFirst(this.monthlyLevelCost, _function);
    boolean _equals = Objects.equal(levelCost, null);
    if (_equals) {MonthlyLevelCost monthlyLevelCost=MonthlyLevelCostImpl.create(getObjectFactory());
      final Procedure1<MonthlyLevelCost> _function_1 = new Procedure1<MonthlyLevelCost>() {
          public void apply(final MonthlyLevelCost it) {
            it.setMonth(mon);
          }
        };
      MonthlyLevelCost _doubleArrow = ObjectExtensions.<MonthlyLevelCost>operator_doubleArrow(monthlyLevelCost, _function_1);
      levelCost = _doubleArrow;
      this.addtoMonthlyLevelCost(levelCost);
    }
    Double _avgEngineerLevelCost = engineerDAO.getAvgEngineerLevelCost(this.level, mon);
    levelCost.setAvgCost(_avgEngineerLevelCost);
  }
  
  public Double getLatestAvgCost() {
    Double _xblockexpression = null;
    {
      final Function1<MonthlyLevelCost,Date> _function = new Function1<MonthlyLevelCost,Date>() {
          public Date apply(final MonthlyLevelCost it) {
            Date _month = it.getMonth();
            Date _trim2Month = DateUtil.trim2Month(_month);
            return _trim2Month;
          }
        };
      List<MonthlyLevelCost> _sortBy = this.monthlyLevelCost==null?(List<MonthlyLevelCost>)null:IterableExtensions.<MonthlyLevelCost, Date>sortBy(this.monthlyLevelCost, _function);
      List<MonthlyLevelCost> _reverse = ListExtensions.<MonthlyLevelCost>reverse(_sortBy);
      MonthlyLevelCost _head = _reverse==null?(MonthlyLevelCost)null:IterableExtensions.<MonthlyLevelCost>head(_reverse);
      Double r = _head==null?(Double)null:_head.getAvgCost();
      boolean _equals = Objects.equal(r, null);
      if (_equals) {
        r = Double.valueOf(0d);
      }
      _xblockexpression = (r);
    }
    return _xblockexpression;
  }
  
  public static EngineerLevelSalary create(final IObjectFactory objectFactory) {
    com.shrcl.engineerprocess.domain.EngineerLevelSalary engineerLevelSalary = new com.shrcl.engineerprocess.domain.impl.EngineerLevelSalaryImpl(
    );
    objectFactory.create(engineerLevelSalary);
    return engineerLevelSalary;			
    
  }
  
  public static EngineerLevelSalary createEngineerLevelSalaryImpl(final IObjectFactory objectFactory, final Procedure1<EngineerLevelSalary> init) {
    com.shrcl.engineerprocess.domain.EngineerLevelSalary engineerLevelSalary = new com.shrcl.engineerprocess.domain.impl.EngineerLevelSalaryImpl(
    );
    objectFactory.create(engineerLevelSalary);
    init.apply(engineerLevelSalary);
    
    return engineerLevelSalary;			
    
  }
  
  public EngineerLevelSalaryProxy toProxy() {
    com.shrcl.engineerprocess.domain.proxy.EngineerLevelSalaryProxy proxy = new com.shrcl.engineerprocess.domain.proxy.EngineerLevelSalaryProxy();
    proxy.setId(this.getId());
    if(this instanceof edu.fudan.mylang.pf.INamedModelObject){
    	proxy.setName(((edu.fudan.mylang.pf.INamedModelObject)this).getEntityName());
    }
    return proxy;
    
  }
}
